/*
 * @FileName: [RoleController.java]
 * 
 * @Package com.bcinfo.upp.admin.ac.controller
 * 
 * 
 * Copyright (c) 2011-2015 BCINFO Technology Limited Com. All rights reserved.
 * 
 * This software is the confidential and proprietary information of BCINFO
 * Technology Limited Company ("Confidential Information"). You shall not
 * disclose such Confidential Information and shall use it only in accordance
 * with the terms of the contract agreement you entered into with RKY.
 * 
 * $Rev: 42 $ $LastChangedDate: 2013-10-12 10:19:36 +0800 (星期六, 12 十月 2013) $
 * $LastChangedBy: wanggc $
 * 
 * @category bcinfo-upp
 * 
 * @version 1.1
 * 
 * @author $Author: wanggc $
 * 
 * Change History:[Formatter: author date description] <br/> 1 2 3
 */

package com.bcinfo.iccard.admin.ac.controller;

import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.bcinfo.iccard.admin.common.ModuleEnum;
import com.bcinfo.iccard.admin.controller.AbstractController;
import com.bcinfo.upp.ac.model.Operator;
import com.bcinfo.upp.ac.model.Role;
import com.bcinfo.upp.ac.service.PermissionService;
import com.bcinfo.upp.ac.service.RoleService;
import com.bcinfo.upp.ac.util.AcConstant;
import com.bcinfo.upp.ac.util.PermissionUtil;
import com.bcinfo.upp.exception.InvalidParametersException;
import com.bcinfo.upp.exception.UppDataBaseException;
import com.bcinfo.upp.exception.UppException;

/**
 * 用户角色管理 <br/>
 * <p>
 * Description:<br/>
 * <p>
 * 
 * <p>
 * listTree返回ztreejson数据 toListTreeView条状到树形页面 add保存到数据库 toAddView跳转到添加页面 update更新到数据库 toUpdateView跳转到更新页面
 * 
 * 
 * <PRE>
 * 
 * </PRE>
 * <p>
 */
@Controller
@RequestMapping("/ac/role")
public class RoleController extends AbstractController
{

    private final static Logger _logger = Logger.getLogger(RoleController.class);

    @Autowired()
    private RoleService         _roleService;

    @Autowired()
    private PermissionService   _permissionService;

    /**
     * 
     * 
     * 按照父类id查找孩子节点，返回树形TreeNode集合的json数据<br/>
     * <p>
     * <br/>
     * <p>
     * Author: chenyc<br/>
     * <p>
     * Date: 2013-4-26-上午09:12:58<br/>
     * <p>
     * 
     * @param request
     * @return 以ajax方式返回处理结果
     * 
     */
    @RequestMapping("/listTree")
    @ResponseBody
    public List<TreeNode> listTree()
    {
        if (!this.hasPermission(ModuleEnum.Role.view))// 没有权限
        {
            return null;
        }
        List<Role> all = null;
        try
        {

            if (request.getParameter("id") == null)
            {
                if (this.getCurrentOperator().getOwner() == -1)
                {// 超级管理员
                    all = _roleService.listAllChildRoles(0l);

                }
                else
                {
                    all = _roleService.findByOwner(getOperatorId());

                }
            }
            else
            {
                // not use now,may use layer for children
                // all =
                // _roleService.listAllChildRoles(Long.parseLong(request.getParameter("id")));
            }

        }
        catch (UppException e)
        {
            handleException(e);
            addLog(ModuleEnum.Role.view, "operatorId=" + getOperatorId() + "|desc=查询角色权限失败");
        }
        catch (Exception e)
        {
            handleException(e);
            addLog(ModuleEnum.Role.view, "operatorId=" + getOperatorId() + "|desc=查询角色权限失败");
        }

        return this.getTreeNode(all);
    }

    /**
     * 
     * 
     * 跳转到角色树形展示界面 <br/>
     * <p>
     * <br/>
     * <p>
     * Author: chenyc<br/>
     * <p>
     * Date: 2013-4-26-上午09:14:16<br/>
     * <p>
     * 
     * @return
     * 
     */
    @RequestMapping("/toListTreeView")
    public ModelAndView toListTreeView()
    {

        ModelAndView mv = new ModelAndView("ac/role/role_list_tree");
        return mv;
    }

    /**
     * 
     * 保存权限设置<br/>
     * <p>
     * <br/>
     * <p>
     * Author: chenyc<br/>
     * <p>
     * Date: 2013-4-24-下午05:49:00<br/>
     * <p>
     * 
     * @param request
     * @param roleId
     * @throws InvalidParameterException
     * @throws UppDataBaseException
     * @throws InvalidParametersException
     * 
     */
    private void addPermission(HttpServletRequest request, long roleId) throws InvalidParameterException,
            UppDataBaseException, InvalidParametersException
    {
        String values[] = request.getParameterValues("shoseactions");

        ResTypeUtil util = new ResTypeUtil();
        if (values != null)
        {

            for (String s : values)
            {
                String arr[] = s.split("_");

                util.put(Long.parseLong(arr[0]), Long.parseLong(arr[1]));
            }
        }
        _permissionService.grantRolePermission(roleId, util.getPermissions());

    }

    /**
     * 
     * 
     * 添加角色和角色的权限配置<br/>
     * <p>
     * <br/>
     * <p>
     * Author: chenyc<br/>
     * <p>
     * Date: 2013-4-26-上午09:14:54<br/>
     * <p>
     * 
     * @param request
     * @param role
     * @return 以ajax方式返回处理结果
     * 
     */
    @RequestMapping("/add")
    @ResponseBody
    public Map<String, String> add(Role role)
    {
        try
        {
            if (!this.hasPermission(ModuleEnum.Role.add))// 没有权限
            {
                _logger.error("权限不足");
                return packageAjaxReturnMap(ERROR_VALUE_OP_RESULT_FAIL, ERROR_VALUE_MSG_TYPE_ERROR, null, "权限不足");
            }
            if (StringUtils.isEmpty(role.getRoleName()))
            {
                _logger.error("角色名字为空");
                return packageAjaxReturnMap(ERROR_VALUE_OP_RESULT_FAIL, ERROR_VALUE_MSG_TYPE_ERROR, null, "角色名字为空");
            }
            role.setStatus(AcConstant.VALID);
            role.setCreateTime(new Date());
            Operator operatorOwner = getCurrentOperator();
            role.setOwner(operatorOwner.getOperatorId());
            long roleid = _roleService.add(role);
            if (!StringUtils.isEmpty(request.getParameter("shoseactions")))
                addPermission(request, roleid);
            addLog(ModuleEnum.Role.add, "operatorId=" + getOperatorId() + "|desc=角色添加成功");
            return packageAjaxReturnMap(ERROR_VALUE_OP_RESULT_SUCCESS, ERROR_VALUE_MSG_TYPE_INFO,
                    ERROR_VALUE_OP_RESULT_SUCCESS_NAME, null);
        }
        catch (UppException e)
        {
            addLog(ModuleEnum.Role.add, "operatorId=" + getOperatorId() + "|desc=角色添加失败");
            return packageUppException(e);
        }
        catch (Exception e)
        {
            addLog(ModuleEnum.Role.add, "operatorId=" + getOperatorId() + "|desc=角色添加失败");
            return packageException(e);
        }

    }

    /**
     * 转到新增页面 <br/>
     * <p>
     * Description: 转到新增页面 <br/>
     * <p>
     * Author: chenyc<br/>
     * <p>
     * Date: 2013-4-17-上午11:30:01<br/>
     * <p>
     * 
     * @return ModelAndView
     * 
     */
    @RequestMapping("/toAddView")
    public ModelAndView toAddView()
    {

        ModelAndView mv = new ModelAndView("ac/role/role_add_frag");
        try
        {
            List<Role> all = _roleService.listAll();
            mv.addObject("roles", all);
        }
        catch (UppDataBaseException e)
        {
            handleException(e);
        }
        mv.addObject("nextaction", "add");
        mv.addObject("formtitle", "新增");
        return mv;
    }

    /**
     * 转到编辑页面 <br/>
     * <p>
     * Description: 转到编辑页面 <br/>
     * <p>
     * Author: chenyc<br/>
     * <p>
     * Date: 2013-4-17-上午11:30:01<br/>
     * <p>
     * 
     * @return ModelAndView
     * 
     */
    @RequestMapping("/toEditView")
    public ModelAndView toEditView()
    {

        ModelAndView mv = new ModelAndView("ac/role/role_add_frag");
        if (!this.hasPermission(ModuleEnum.Role.update))// 没有权限
        {
            mv.addObject("updateCode", ModuleEnum.Role.update);
            mv.addObject("createCode", ModuleEnum.Role.add);
            return null;
        }
        try
        {
            Role r = _roleService.findById(Long.parseLong(request.getParameter("roleId")));
            mv.addObject("role", r);
            mv.addObject("nextaction", "update");
        }
        catch (UppDataBaseException e)
        {
            handleException(e);
        }
        mv.addObject("formtitle", "编辑");

        return mv;
    }

    /**
     * 
     * 
     * 更新角色数据和角色权限配置数据<br/>
     * <p>
     * <br/>
     * <p>
     * Author: chenyc<br/>
     * <p>
     * Date: 2013-4-26-上午09:15:45<br/>
     * <p>
     * 
     * @param request
     * @param role
     * @return 以ajax方式返回处理结果
     * 
     */
    @RequestMapping("/update")
    @ResponseBody
    public Map<String, String> update(Role role)
    {
        try
        {
            if (!this.hasPermission(ModuleEnum.Role.update))// 没有权限
            {
                _logger.error("权限不足");
                return packageAjaxReturnMap(ERROR_VALUE_OP_RESULT_FAIL, ERROR_VALUE_MSG_TYPE_ERROR, null, "权限不足");
            }
            // 只能修改自己拥有的角色
            Role roledb = _roleService.findById(role.getRoleId());

            if (roledb.getOwner() != this.getOperatorId() && this.getCurrentOperator().getOwner() != -1)
            {
                _logger.error("只能修改自己拥有的角色");
                return packageAjaxReturnMap(ERROR_VALUE_OP_RESULT_FAIL, ERROR_VALUE_MSG_TYPE_ERROR, null, "权限不足");
            }

            role.setStatus(AcConstant.VALID);
            _roleService.update(role);
            if (!StringUtils.isEmpty(request.getParameter("shoseactions")))
                addPermission(request, role.getRoleId());

            addLog(ModuleEnum.Role.update, "operatorId=" + getOperatorId() + "|desc=角色编辑成功");

            return packageAjaxReturnMap(ERROR_VALUE_OP_RESULT_SUCCESS, ERROR_VALUE_MSG_TYPE_INFO,
                    ERROR_VALUE_OP_RESULT_SUCCESS_NAME, null);
        }
        catch (UppException e)
        {
            addLog(ModuleEnum.Role.update, "operatorId=" + getOperatorId() + "|desc=角色编辑失败");
            return packageUppException(e);
        }
        catch (Exception e)
        {
            addLog(ModuleEnum.Role.update, "operatorId=" + getOperatorId() + "|desc=角色编辑失败");
            return packageException(e);
        }

    }

    /**
     * 
     * 
     * 删除角色和角色权限配置信息 <br/>
     * <p>
     * <br/>
     * <p>
     * Author: chenyc<br/>
     * <p>
     * Date: 2013-4-26-上午09:18:05<br/>
     * <p>
     * 
     * @param request
     * @return 以ajax方式返回处理结果
     * 
     */
    @RequestMapping("/remove")
    @ResponseBody
    public Map<String, String> remove()
    {
        try
        {
            if (!this.hasPermission(ModuleEnum.Role.remove))// 没有权限
            {
                _logger.error("权限不足");
                return packageAjaxReturnMap(ERROR_VALUE_OP_RESULT_FAIL, ERROR_VALUE_MSG_TYPE_ERROR, null, "权限不足");
            }
            long roleId = Long.parseLong(request.getParameter("roleId"));
            // 权限关系在服务端完成删除
            _roleService.delete(roleId);
            addLog(ModuleEnum.Role.remove, "operatorId=" + getOperatorId() + "|desc=角色删除成功");

            return packageAjaxReturnMap(ERROR_VALUE_OP_RESULT_SUCCESS, ERROR_VALUE_MSG_TYPE_INFO,
                    ERROR_VALUE_OP_RESULT_SUCCESS_NAME, null);
        }
        catch (UppException e)
        {
            addLog(ModuleEnum.Role.remove, "operatorId=" + getOperatorId() + "|desc=角色删除失败");
            return packageUppException(e);
        }
        catch (Exception e)
        {
            addLog(ModuleEnum.Role.remove, "operatorId=" + getOperatorId() + "|desc=角色删除失败");
            return packageException(e);
        }

    }

    /**
     * 
     * 
     * 转换数据使用，数据库数据，转化为ztree，json数据 <br/>
     * <p>
     * <br/>
     * <p>
     * Author: chenyc<br/>
     * <p>
     * Date: 2013-4-18-下午05:45:17<br/>
     * <p>
     * 
     * @param roles
     * @return
     * 
     */
    private List<TreeNode> getTreeNode(List<Role> roles)
    {

        List<TreeNode> nodes = new ArrayList<TreeNode>();

        for (Role role : roles)
        {
            TreeNode t = new TreeNode();
            t.setId(role.getRoleId().toString());
            if (role.getChildRoles() != null && role.getChildRoles().size() > 0)
            {
                t.setIsParent("true");
            }
            else
            {
                t.setIsParent("false");
            }
            t.setName(role.getRoleName());
            if (role.getSuperRole() != null)
            {
                t.setPid(role.getSuperRole().getRoleId().toString());
            }
            nodes.add(t);
        }
        return nodes;

    }

    /**
     * 
     * 
     * ztree树行节点json <br/>
     * <p>
     * Description:<br/>
     * <p>
     * For Examples <br/>
     * 
     * <PRE>
     * 
     * </PRE>
     * <p>
     */
    class TreeNode
    {
        String _id;

        String _name;

        String _isParent;

        String _pid;

        public String getId()
        {
            return _id;
        }

        public void setId(String id)
        {
            _id = id;
        }

        public String getName()
        {
            return _name;
        }

        public void setName(String name)
        {
            _name = name;
        }

        public String getIsParent()
        {
            return _isParent;
        }

        public void setIsParent(String isParent)
        {
            _isParent = isParent;
        }

        public String getPid()
        {
            return _pid;
        }

        public void setPid(String pid)
        {
            _pid = pid;
        }

    }

    /**
     * 
     * 
     * 用于将资源结合码 数据转换为一个数据， @see
     * 
     * com.bcinfo.upp.ac.util.PermissionUtil.getactions<br/>
     * <p>
     * 
     * 
     * 
     * <p>
     * 
     * 
     * <PRE>
     * 
     * </PRE>
     * <p>
     */
    class ResTypeUtil
    {

        public ResTypeUtil()
        {

        }

        Map<Long, List<Long>> resss = new HashMap<Long, List<Long>>();

        /**
         * 
         * 
         * 获取转换后 Map<Long, Long> <br/>
         * <p>
         * key ResourceType.typeid， value:ResourceAction集合的|运算的long值 <br/>
         * <p>
         * Author: chenyc<br/>
         * <p>
         * Date: 2013-4-26-下午04:26:06<br/>
         * <p>
         * 
         * @return
         * 
         */
        public Map<Long, Long> getPermissions()
        {
            Map<Long, Long> map = new HashMap<Long, Long>();
            Set<Long> keys = resss.keySet();
            for (Long k : keys)
            {
                List<Long> actions = resss.get(k);
                Long[] vals = new Long[actions.size()];
                map.put(k, (PermissionUtil.getActions(actions.toArray(vals))));
            }
            return map;
        }

        /**
         * 
         * 
         * 把资源的操作码存起来，1对多<br/>
         * <p>
         * key ResourceType.typeid, values：list的ResourceAction.bitwiseValue <br/>
         * <p>
         * Author: chenyc<br/>
         * <p>
         * Date: 2013-4-26-下午04:22:43<br/>
         * <p>
         * 
         * @param resid
         * @param actionid
         * 
         */
        public void put(Long resid, Long actionid)
        {
            if (resss.get(resid) != null)
            {
                resss.get(resid).add(actionid);

            }
            else
            {
                List<Long> actions = new ArrayList<Long>();
                actions.add(actionid);
                resss.put(resid, actions);
            }

        }

    }

    /*
     * (non-Javadoc) Description: <br/>
     * 
     * @return
     * 
     * @see com.bcinfo.upp.admin.controller.AdminController#getMouduleCode()
     */
    public String getMouduleCode()
    {
        return ModuleEnum.Role.moduleName.value;
    }
}
